package com.mxgraph.io.vdx;

import com.mxgraph.util.mxPoint;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.List;

/**
 * This class is a general wrapper for one Shape Element.<br/>
 * Provides a set of method for retrieve the value of the diferents properties
 * stored in the shape element.<br/>
 * References to other shapes or stylesheets are not considered.
 */
public class mxGeneralShape {
    protected Element shape;

    /**
     * Create a new instance of mxGeneralShape
     *
     * @param shape Shape Element to be wrapped.
     */
    public mxGeneralShape(Element shape) {
        this.shape = shape;
    }

    /**
     * Returns the shape contained.
     *
     * @return Shape Element contained.
     */
    public Element getShape() {
        return shape;
    }

    /**
     * Sets the shape to be contained.
     *
     * @param shape Shape Element to be contained.
     */
    public void setShape(Element shape) {
        this.shape = shape;
    }

    /**
     * Returns the id of the stylesheet that contains the fill style.
     *
     * @return ID of the stylesheet.
     */
    public String getFillStyleId() {
        return shape.getAttribute(mxVdxConstants.FILL_STYLE);
    }

    /**
     * Returns the id of the stylesheet that contains the line style
     *
     * @return ID of the stylesheet.
     */
    public String getLineStyleId() {
        return shape.getAttribute(mxVdxConstants.LINE_STYLE);
    }

    /**
     * Returns the id of the stylesheet that contains the text style
     *
     * @return ID of the stylesheet.
     */
    public String getTextStyleId() {
        return shape.getAttribute(mxVdxConstants.TEXT_STYLE);
    }

    /**
     * Checks if the shape Element has a children with tag name = 'tag'.
     *
     * @param tag Name of the Element to be found.
     * @return Returns <code>true</code> if the shape Element has a children with tag name = 'tag'
     */
    protected boolean hasPrimaryTag(String tag) {
        boolean ret = false;
        NodeList childrens = shape.getChildNodes();
        if (mxVdxUtils.nodeListHasTag(childrens, tag)) {
            ret = true;
        } else {
            ret = false;

        }
        return ret;
    }

    /**
     * Returns the element with tag name = 'tag' in the childrens of shape
     *
     * @param tag Name of the Element to be found.
     * @return Element with tag name = 'tag'.
     */
    protected Element getPrimaryTag(String tag) {
        NodeList childrens = shape.getChildNodes();
        Element primary = null;
        if (mxVdxUtils.nodeListHasTag(childrens, tag)) {
            primary = mxVdxUtils.nodeListTag(childrens, tag);
        }
        return primary;
    }

    /**
     * Returns the element with tag name = 'tag' and IX attribute = 'ix' in the childrens of shape.
     *
     * @param tag Name of the Element to be found.
     * @param ix  Index of the Element to be found.
     * @return Element with tag name = 'tag' and IX attribute = 'ix'.
     */
    protected Element getPrimaryTagIndexed(String tag, String ix) {
        NodeList childrens = shape.getChildNodes();
        Element primary = null;
        if (mxVdxUtils.nodeListHasTag(childrens, tag)) {
            primary = mxVdxUtils.nodeListTagIndexed(childrens, tag, ix);
        }
        return primary;
    }

    /**
     * Checks if the 'primary' Element has a children with tag name = 'tag'.
     *
     * @param tag Name of the Element to be found.
     * @return Returns <code>true</code> if the 'primary' Element has a children with tag name = 'tag'.
     */
    protected boolean hasSecundaryTag(Element primary, String tag) {
        NodeList xChildrens = null;
        boolean ret = false;
        if (primary != null) {
            xChildrens = primary.getChildNodes();
        }
        if (mxVdxUtils.nodeListHasTag(xChildrens, tag)) {
            ret = true;
        } else {
            ret = false;
        }
        return ret;
    }

    /**
     * Returns the value of the element with tag name = 'tag' in the childrens
     * of 'primary' in his double representation.<br/>
     * .vdx uses Inches for numerical representations, so this value
     * is multiplied by the result of <code>mxVdxUtils.conversionFactor()</code>
     * and is converted to pixels.
     *
     * @param tag Name of the Element to be found.
     * @return Numerical value of the element.
     */
    protected double getNumericalValueOfSecundaryTag(Element primary, String tag) {
        double val = 0;
        NodeList xChildrens = null;
        if (primary != null) {
            xChildrens = primary.getChildNodes();
        }
        Element elem = null;

        if (mxVdxUtils.nodeListHasTag(xChildrens, tag)) {
            elem = mxVdxUtils.nodeListTag(xChildrens, tag);
        }

        if (elem != null) {
            val = Double.parseDouble(elem.getTextContent())
                    * mxVdxUtils.conversionFactor();
        }
        return val;
    }

    /**
     * Returns the value of the element with tag name = 'tag' in the childrens
     * of primary.
     *
     * @param tag Name of the Element to be found.
     * @return String value of the element.
     */
    protected String getValueOfSecundaryTag(Element primary, String tag) {
        String val = "";
        NodeList xChildrens = null;
        if (primary != null) {
            xChildrens = primary.getChildNodes();
        }
        Element elem = null;
        if (mxVdxUtils.nodeListHasTag(xChildrens, tag)) {
            elem = mxVdxUtils.nodeListTag(xChildrens, tag);
            val = elem.getTextContent();
        }

        return val;
    }

    /**
     * Check if the shape has defined a pinX element.
     *
     * @return Returns <code>true</code> if the shape has defined a pinX element.
     */
    public boolean hasPinX() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        return hasSecundaryTag(xForm, mxVdxConstants.PIN_X);
    }

    /**
     * Returns the value of the pinX element.
     *
     * @return The shape pinX element
     */
    public double getPinX() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        double px = 0;
        if (hasSecundaryTag(xForm, mxVdxConstants.PIN_X)) {
            px = getNumericalValueOfSecundaryTag(xForm, mxVdxConstants.PIN_X);
        }
        return px;
    }

    /**
     * Returns <code>true</code> if the shape has defined a pinY element.
     *
     * @return Returns <code>true</code> if the shape has defined a pinY element.
     */
    public boolean hasPinY() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        return hasSecundaryTag(xForm, mxVdxConstants.PIN_Y);
    }

    /**
     * Returns the value of the pinY element in pixels.
     *
     * @return Numerical value of the pinY element.
     */
    public double getPinY() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        double py = 0;
        if (hasSecundaryTag(xForm, mxVdxConstants.PIN_Y)) {
            py = getNumericalValueOfSecundaryTag(xForm, mxVdxConstants.PIN_Y);
        }
        return py;
    }

    /**
     * Check if the shape has defined a locPinX element.
     *
     * @return Returns <code>true</code> if the shape has defined a locPinX element.
     */
    public boolean hasLocPinX() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        return hasSecundaryTag(xForm, mxVdxConstants.LOC_PIN_X);
    }

    /**
     * Returns the value of the locPinX element in pixels.
     *
     * @return Numerical value of the pinY element.
     */
    public double getLocPinX() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        double py = 0;
        if (hasSecundaryTag(xForm, mxVdxConstants.LOC_PIN_X)) {
            py = getNumericalValueOfSecundaryTag(xForm,
                    mxVdxConstants.LOC_PIN_X);
        }
        return py;
    }

    /**
     * Check if the shape has defined a locPinY element.
     *
     * @return Returns <code>true</code> if the shape has defined a locPinY element.
     */
    public boolean hasLocPinY() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        return hasSecundaryTag(xForm, mxVdxConstants.LOC_PIN_Y);

    }

    /**
     * Returns the value of the locPinY element in pixels.
     *
     * @return Numerical value of the locPinY element.
     */
    public double getLocPinY() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        double py = 0;
        if (hasSecundaryTag(xForm, mxVdxConstants.LOC_PIN_Y)) {
            py = getNumericalValueOfSecundaryTag(xForm,
                    mxVdxConstants.LOC_PIN_Y);
        }
        return py;
    }

    /**
     * Checks if the shape has defined a width element.
     *
     * @return Returns <code>true</code> if the shape has defined a width element.
     */
    public boolean hasWidth() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        return hasSecundaryTag(xForm, mxVdxConstants.WIDTH);
    }

    /**
     * Returns the value of the width element in pixels.
     *
     * @return Numerical value of the width element.
     */
    public double getWidth() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        double w = 0;
        if (hasSecundaryTag(xForm, mxVdxConstants.WIDTH)) {
            w = getNumericalValueOfSecundaryTag(xForm, mxVdxConstants.WIDTH);
        }
        return w;
    }

    /**
     * Checks if the shape has defined a height element.
     *
     * @return Returns <code>true</code> if the shape has defined a height element.
     */
    public boolean hasHeight() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        return hasSecundaryTag(xForm, mxVdxConstants.HEIGHT);
    }

    /**
     * Returns the value of the height element in pixels.
     *
     * @return Numerical value of the height element.
     */
    public double getHeight() {
        Element xForm = getPrimaryTag(mxVdxConstants.X_FORM);
        double h = 0;
        if (hasSecundaryTag(xForm, mxVdxConstants.HEIGHT)) {
            h = getNumericalValueOfSecundaryTag(xForm, mxVdxConstants.HEIGHT);
        }
        return h;
    }

    /**
     * Checks if back ground color of the Shape is defined.
     *
     * @return Returns <code>true</code> if back ground color of the Shape is defined.
     */
    public boolean hasFillColor() {
        Element xForm = getPrimaryTag(mxVdxConstants.FILL);
        return hasSecundaryTag(xForm, mxVdxConstants.FILL_BKGND);
    }

    /**
     * Returns the background color.
     *
     * @return Background color in hexadecimal representation.
     */
    public String getFillColor() {

        Element fill = getPrimaryTag(mxVdxConstants.FILL);
        String color = "";
        if (hasSecundaryTag(fill, mxVdxConstants.FILL_BKGND)) {
            color = getValueOfSecundaryTag(fill, mxVdxConstants.FILL_BKGND);
        }
        if (!color.startsWith("#")) {
            mxPropertiesManager pm = mxPropertiesManager.getInstance();
            color = pm.getColor(color);
        }
        return color;
    }

    /**
     * Checks if foreground color of the Shape is defined.
     *
     * @return Returns <code>true</code> if foreground color of the Shape is defined.
     */
    public boolean hasFillForeColor() {
        Element xForm = getPrimaryTag(mxVdxConstants.FILL);
        return hasSecundaryTag(xForm, mxVdxConstants.FILL_FOREGND);
    }

    /**
     * Returns the foreground color.
     *
     * @return Foreground color in hexadecimal representation.
     */
    public String getFillForeColor() {

        Element fill = getPrimaryTag(mxVdxConstants.FILL);
        String color = "";
        if (hasSecundaryTag(fill, mxVdxConstants.FILL_FOREGND)) {
            color = getValueOfSecundaryTag(fill, mxVdxConstants.FILL_FOREGND);
        }
        if (!color.startsWith("#")) {
            mxPropertiesManager pm = mxPropertiesManager.getInstance();
            color = pm.getColor(color);
        }
        return color;
    }

    /**
     * Checks if pattern of the Shape is defined.
     *
     * @return Returns <code>true</code> if pattern of the Shape is defined.
     */
    public boolean hasFillPattern() {
        Element xForm = getPrimaryTag(mxVdxConstants.FILL);
        return hasSecundaryTag(xForm, mxVdxConstants.FILL_PATTERN);
    }

    /**
     * Returns the pattern.
     *
     * @return String value of the FillPattern element.
     */
    public String getFillPattern() {

        Element fill = getPrimaryTag(mxVdxConstants.FILL);
        String pattern = "";
        if (hasSecundaryTag(fill, mxVdxConstants.FILL_PATTERN)) {
            pattern = getValueOfSecundaryTag(fill, mxVdxConstants.FILL_PATTERN);
        }
        return pattern;
    }

    /**
     * Checks if shadow pattern of the Shape is defined.
     *
     * @return Returns <code>true</code> if shadow pattern of the Shape is defined.
     */
    public boolean hasShdwPattern() {
        Element xForm = getPrimaryTag(mxVdxConstants.FILL);
        return hasSecundaryTag(xForm, mxVdxConstants.SHDW_PATTERN);
    }

    /**
     * Returns the shadow pattern.
     *
     * @return String value of the ShdwPattern Element
     */
    public String getShdwPattern() {

        Element fill = getPrimaryTag(mxVdxConstants.FILL);
        String pattern = "";
        if (hasSecundaryTag(fill, mxVdxConstants.SHDW_PATTERN)) {
            pattern = getValueOfSecundaryTag(fill, mxVdxConstants.SHDW_PATTERN);
        }
        return pattern;
    }

    /**
     * Checks if pattern of the line is defined.
     *
     * @return Returns <code>true</code> if pattern of the line is defined.
     */
    public boolean hasLinePattern() {
        Element xForm = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(xForm, mxVdxConstants.LINE_PATTERN);
    }

    /**
     * Returns the line pattern of the shape
     *
     * @return String value of the LinePattern element.
     */
    public String getLinePattern() {
        Element fill = getPrimaryTag(mxVdxConstants.LINE);
        String pattern = "";
        if (hasSecundaryTag(fill, mxVdxConstants.LINE_PATTERN)) {
            pattern = getValueOfSecundaryTag(fill, mxVdxConstants.LINE_PATTERN);
        }
        return pattern;
    }

    /**
     * Checks if begin arrow of the line is defined.
     *
     * @return Returns <code>true</code> if begin arrow of the line is defined.
     */
    public boolean hasBeginArrow() {
        Element xForm = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(xForm, mxVdxConstants.BEGIN_ARROW);

    }

    /**
     * Returns the line begin arrow of the shape
     *
     * @return String value of the BeginArrow element.
     */
    public String getBeginArrow() {
        Element fill = getPrimaryTag(mxVdxConstants.LINE);
        String arrow = "";
        if (hasSecundaryTag(fill, mxVdxConstants.BEGIN_ARROW)) {
            arrow = getValueOfSecundaryTag(fill, mxVdxConstants.BEGIN_ARROW);
        }
        return arrow;
    }

    /**
     * Checks if end arrow of the line is defined.
     *
     * @return Returns <code>true</code> if end arrow of the line is defined.
     */
    public boolean hasEndArrow() {
        Element xForm = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(xForm, mxVdxConstants.END_ARROW);
    }

    /**
     * Returns the line end arrow of the shape
     *
     * @return String value of the EndArrow element.
     */
    public String getEndArrow() {
        Element fill = getPrimaryTag(mxVdxConstants.LINE);
        String arrow = "";
        if (hasSecundaryTag(fill, mxVdxConstants.END_ARROW)) {
            arrow = getValueOfSecundaryTag(fill, mxVdxConstants.END_ARROW);
        }
        return arrow;
    }

    /**
     * Checks if begin arrow size of the line is defined.
     *
     * @return Returns <code>true</code> if begin arrow size of the line is defined.
     */
    public boolean hasBeginArrowSize() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(line, mxVdxConstants.BEGIN_ARROW_SIZE);

    }

    /**
     * Returns the line begin arrow size of the shape
     *
     * @return String value of the BeginArrowSize element.
     */
    public String getBeginArrowSize() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        String size = "";
        if (hasSecundaryTag(line, mxVdxConstants.BEGIN_ARROW_SIZE)) {
            size = getValueOfSecundaryTag(line, mxVdxConstants.BEGIN_ARROW_SIZE);
        }
        return size;
    }

    /**
     * Checks if end arrow size of the line is defined.
     *
     * @return Returns <code>true</code> if end arrow size of the line is defined.
     */
    public boolean hasEndArrowSize() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(line, mxVdxConstants.END_ARROW_SIZE);

    }

    /**
     * Returns the line end arrow size of the shape
     *
     * @return String value of the EndArrowSize element.
     */
    public String getEndArrowSize() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        String size = "";
        if (hasSecundaryTag(line, mxVdxConstants.END_ARROW_SIZE)) {
            size = getValueOfSecundaryTag(line, mxVdxConstants.END_ARROW_SIZE);
        }
        return size;
    }

    /**
     * Checks if the line weight is defined.
     *
     * @return Returns <code>true</code> if the line weight is defined.
     */
    public boolean hasLineWeight() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(line, mxVdxConstants.LINE_WEIGHT);
    }

    /**
     * Returns the line weight of the shape in pixels
     *
     * @return Numerical value of the LineWeight element.
     */
    public double getLineWeight() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        double lw = 0;
        if (hasSecundaryTag(line, mxVdxConstants.LINE_WEIGHT)) {
            lw = getNumericalValueOfSecundaryTag(line,
                    mxVdxConstants.LINE_WEIGHT);
        }
        return lw;
    }

    /**
     * Checks if line color of the Shape is defined.
     *
     * @return Returns <code>true</code> if line color of the Shape is defined.
     */
    public boolean hasLineColor() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(line, mxVdxConstants.LINE_COLOR);
    }

    /**
     * Returns the line color.
     *
     * @return Line color of the shape in hexadecimal representation.
     */
    public String getLineColor() {

        Element line = getPrimaryTag(mxVdxConstants.LINE);
        String color = "";
        if (hasSecundaryTag(line, mxVdxConstants.LINE_COLOR)) {
            color = getValueOfSecundaryTag(line, mxVdxConstants.LINE_COLOR);
        }
        if (!color.startsWith("#")) {
            mxPropertiesManager pm = mxPropertiesManager.getInstance();
            color = pm.getColor(color);
        }
        return color;
    }

    /**
     * Checks if the rounding factor of the Shape is defined.
     *
     * @return Returns <code>true</code> if line color of the Shape is defined.
     */
    public boolean hasRounding() {
        Element line = getPrimaryTag(mxVdxConstants.LINE);
        return hasSecundaryTag(line, mxVdxConstants.ROUNDING);
    }

    /**
     * Returns the rounding factor.
     *
     * @return Value of the Rounding element
     */
    public double getRounding() {

        Element line = getPrimaryTag(mxVdxConstants.LINE);
        double r = 0;
        if (hasSecundaryTag(line, mxVdxConstants.ROUNDING)) {
            String val = "";
            val = getValueOfSecundaryTag(line, mxVdxConstants.ROUNDING);
            if (!val.equals("")) {
                r = Double.valueOf(val);
            }
        }
        return r;
    }

    /**
     * Checks if transparence of the Shape is defined.
     *
     * @return Returns <code>true</code> if transparence of the Shape is defined.
     */
    public boolean hasTransparence() {
        Element fill = getPrimaryTag(mxVdxConstants.FILL);
        return hasSecundaryTag(fill, mxVdxConstants.FILL_BKGND_TRANS);
    }

    /**
     * Returns the level of transparence of the Shape.
     *
     * @return double in range (opaque = 0)..(100 = transparent)
     */
    public double getTransparence() {
        Element fill = getPrimaryTag(mxVdxConstants.FILL);
        double trans = 0;
        if (hasSecundaryTag(fill, mxVdxConstants.FILL_BKGND_TRANS)) {
            trans = getNumericalValueOfSecundaryTag(fill,
                    mxVdxConstants.FILL_BKGND_TRANS);
        }
        return trans;
    }

    /**
     * Checks if angle of the Shape is defined.
     *
     * @return Returns <code>true</code> if angle of the Shape is defined.
     */
    public boolean hasAngle() {
        Element fill = getPrimaryTag(mxVdxConstants.X_FORM);
        return hasSecundaryTag(fill, mxVdxConstants.ANGLE);
    }

    /**
     * Returns the rotation angle of the Shape.
     *
     * @return Value of the Angle element in radians.
     */
    public double getAngle() {
        Element fill = getPrimaryTag(mxVdxConstants.X_FORM);
        double angle = 0;
        if (hasSecundaryTag(fill, mxVdxConstants.ANGLE)) {
            String rot = "0";
            rot = getValueOfSecundaryTag(fill, mxVdxConstants.ANGLE);
            angle = Double.valueOf(rot);
        }
        return angle;
    }

    /**
     * Checks if the shape has defined a Text element.
     *
     * @return Returns <code>true</code> if the shape has defined a Text element.
     */
    public boolean hasText() {
        return hasPrimaryTag(mxVdxConstants.TEXT);
    }

    /**
     * Returns the value of the Text element.
     *
     * @return Value of the Text element.
     */
    public String getText() {
        String ret = "";
        Element text = getPrimaryTag(mxVdxConstants.TEXT);

        if (text != null) {
            ret = text.getTextContent();
        }
        return ret;
    }

    /**
     * Returns the childrens Nodes of Text.
     *
     * @return List with the childrens of the Text element.
     */
    public List<Node> getTextChildrens() {
        List<Node> list = null;
        Element text = getPrimaryTag(mxVdxConstants.TEXT);
        NodeList child = null;
        if (text != null) {
            child = text.getChildNodes();
            list = mxVdxUtils.copyNodeList(child);
        }
        return list;
    }

    /**
     * Returns the NameU attribute.
     *
     * @return Value of the NameU attribute.
     */
    public String getNameU() {
        String nameU = "";
        if (shape.hasAttribute(mxVdxConstants.NAME_U)) {
            nameU = shape.getAttribute(mxVdxConstants.NAME_U);
        }
        return nameU;
    }

    /**
     * Returns the value of the Id attribute.
     *
     * @return Value of the Id attribute.
     */
    public String getId() {
        return shape.getAttribute(mxVdxConstants.ID);
    }

    /**
     * Checks if the Geom Element of the shape contains the Ellipse element.
     *
     * @return Returns <code>true</code> if the Geom Element of the shape contains the Ellipse element.
     */
    public boolean hasEllipse() {
        Element fill = getPrimaryTag(mxVdxConstants.GEOM);
        return hasSecundaryTag(fill, mxVdxConstants.ELLIPSE);
    }

    /**
     * Returns the amount of LineTo Elements inside of the Geom Element
     *
     * @return Number of LineTo elements.
     */
    public int getAmountLineTo() {
        List<Element> lineTo = new ArrayList<Element>();
        Element Geom = getPrimaryTag(mxVdxConstants.GEOM);
        NodeList xChildrens = null;

        if (Geom != null) {
            xChildrens = Geom.getChildNodes();
        }

        if (mxVdxUtils.nodeListHasTag(xChildrens, mxVdxConstants.LINE_TO)) {
            lineTo = mxVdxUtils
                    .nodeListTags(xChildrens, mxVdxConstants.LINE_TO);
        }
        int a = lineTo.size();
        return a;

    }

    /**
     * Returns the amount of Connection Elements inside of Shape Element.
     *
     * @return Number of Connection Elements.
     */
    public int getAmountConnection() {
        List<Element> lineTo = new ArrayList<Element>();
        NodeList xChildrens = null;

        if (shape != null) {
            xChildrens = shape.getChildNodes();
        }

        if (mxVdxUtils.nodeListHasTag(xChildrens, mxVdxConstants.CONNECTION)) {
            lineTo = mxVdxUtils.nodeListTags(xChildrens,
                    mxVdxConstants.CONNECTION);
        }
        int a = lineTo.size();
        return a;

    }

    /**
     * Returns the amount of EllipticalArcTo Elements inside of Geom Element
     *
     * @return Number of EllipticalArcTo Elements.
     */
    public int getAmountEllipticalArcTo() {
        List<Element> ellipticalArcTo = new ArrayList<Element>();
        Element Geom = getPrimaryTag(mxVdxConstants.GEOM);
        NodeList xChildrens = null;

        if (Geom != null) {
            xChildrens = Geom.getChildNodes();
        }

        if (mxVdxUtils.nodeListHasTag(xChildrens,
                mxVdxConstants.ELLIPTICAL_ARC_TO)) {
            ellipticalArcTo = mxVdxUtils.nodeListTags(xChildrens,
                    mxVdxConstants.ELLIPTICAL_ARC_TO);
        }
        int a = ellipticalArcTo.size();
        return a;

    }

    /**
     * Returns the amount of ArcTo Elements inside of Geom Element
     *
     * @return Number of ArcTo Elements.
     */
    public int getAmountArcTo() {
        List<Element> arcTo = new ArrayList<Element>();
        Element Geom = getPrimaryTag(mxVdxConstants.GEOM);
        NodeList xChildrens = null;

        if (Geom != null) {
            xChildrens = Geom.getChildNodes();
        }

        if (mxVdxUtils.nodeListHasTag(xChildrens, mxVdxConstants.ARC_TO)) {
            arcTo = mxVdxUtils.nodeListTags(xChildrens, mxVdxConstants.ARC_TO);
        }
        int a = arcTo.size();
        return a;
    }

    /**
     * Checks if the shape has the XForm1D element.
     *
     * @return Returns <code>true</code> if the shape has the XForm1D element.
     */
    public boolean hasXForm1D() {
        NodeList childrens = shape.getChildNodes();
        return mxVdxUtils.nodeListHasTag(childrens, mxVdxConstants.X_FORM_1D);
    }

    /**
     * Returns the co-ordinates of the begin point of an Edge Shape.
     *
     * @param parentHeight Height of the parent of the shape.
     * @return mxPoint that represents the co-ordinates.
     */
    public mxPoint getBeginXY(double parentHeight) {
        double beginX = 0;
        double beginY = 0;
        if (hasPrimaryTag(mxVdxConstants.X_FORM_1D)) {
            Element xForm1D = getPrimaryTag(mxVdxConstants.X_FORM_1D);
            if (hasSecundaryTag(xForm1D, mxVdxConstants.BEGIN_X)) {
                beginX = getNumericalValueOfSecundaryTag(xForm1D,
                        mxVdxConstants.BEGIN_X);
            }
            if (hasSecundaryTag(xForm1D, mxVdxConstants.BEGIN_Y)) {
                beginY = parentHeight
                        - getNumericalValueOfSecundaryTag(xForm1D,
                        mxVdxConstants.BEGIN_Y);
            }
        }
        return new mxPoint(beginX, beginY);
    }

    /**
     * Returns the co-ordinates of the end point of an Edge Shape.
     *
     * @param parentHeight Height of the parent of the shape.
     * @return mxPoint that represents the co-ordinates.
     */
    public mxPoint getEndXY(double parentHeight) {
        double endX = 0;
        double endY = 0;
        if (hasPrimaryTag(mxVdxConstants.X_FORM_1D)) {
            Element xForm1D = getPrimaryTag(mxVdxConstants.X_FORM_1D);
            if (hasSecundaryTag(xForm1D, mxVdxConstants.END_X)) {
                endX = getNumericalValueOfSecundaryTag(xForm1D,
                        mxVdxConstants.END_X);
            }
            if (hasSecundaryTag(xForm1D, mxVdxConstants.END_Y)) {
                endY = parentHeight
                        - getNumericalValueOfSecundaryTag(xForm1D,
                        mxVdxConstants.END_Y);
            }
        }
        return new mxPoint(endX, endY);
    }

    /**
     * Returns the list of routing points of a edge shape.
     *
     * @param parentHeight Height of the parent of the shape.
     * @return List of mxPoint that represents the routing points.
     */
    public List<mxPoint> getRoutingPoints(double parentHeight) {
        mxPoint beginXY = getBeginXY(parentHeight);
        ArrayList<mxPoint> pointList = new ArrayList<mxPoint>();
        NodeList lineTos = shape.getElementsByTagName(mxVdxConstants.LINE_TO);
        ArrayList<Element> lineToList = new ArrayList<Element>();

        //Discards deleted elements.
        int numLineTos = lineTos.getLength();

        for (int l = 0; l < numLineTos; l++) {
            Element lineTo = (Element) lineTos.item(l);

            if (!(lineTo.hasAttribute(mxVdxConstants.DELETED) && (lineTo
                    .getAttribute(mxVdxConstants.DELETED)).equals("1"))) {
                lineToList.add(lineTo);
            }
        }

        //Get routing points from LineTo Elements.
        int numPoints = lineToList.size();
        for (int k = 0; (k < (numPoints - 1)); k++) {
            Element lineTo = lineToList.get(k);
            mxPoint lineToXY = getLineToXY(lineTo);
            Double x = (beginXY.getX() + lineToXY.getX());
            Double y = (beginXY.getY() + lineToXY.getY());
            pointList.add(new mxPoint(x, y));
        }

        return pointList;
    }

    /**
     * Returns the xy co-ordinates inside a LineTo Element.
     *
     * @param lineTo LineTo Element
     * @return mxPoint that represents the xy co-ordinates
     */
    public static mxPoint getLineToXY(Element lineTo) {
        Element xElem = (Element) lineTo.getElementsByTagName(mxVdxConstants.X)
                .item(0);

        Element yElem = (Element) lineTo.getElementsByTagName(mxVdxConstants.Y)
                .item(0);

        double lineToX = Double.valueOf(xElem.getTextContent())
                * mxVdxUtils.conversionFactor();
        double lineToY = (Double.valueOf(yElem.getTextContent()) * mxVdxUtils
                .conversionFactor()) * -1;
        return new mxPoint(lineToX, lineToY);
    }

    /**
     * Checks if the color of one text fragment is defined
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if the color of one text fragment is defined.
     */
    public boolean hasTextColor(String charIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        return hasSecundaryTag(ch, mxVdxConstants.COLOR);
    }

    /**
     * Returns the color of one text fragment
     *
     * @param charIX IX atribute of Char element
     * @return Text color in hexadecimal representation.
     */
    public String getTextColor(String charIX) {
        String color = "#000000";
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        if (hasSecundaryTag(ch, mxVdxConstants.COLOR)) {
            color = getValueOfSecundaryTag(ch, mxVdxConstants.COLOR);
            if (!color.startsWith("#")) {
                mxPropertiesManager pm = mxPropertiesManager.getInstance();
                color = pm.getColor(color);
            }
        }
        return color;
    }

    /**
     * Checks if the background color of text is defined
     *
     * @return Returns <code>true</code> if the background color of text is defined.
     */
    public boolean hasTextBkgndColor() {
        Element ch = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        return hasSecundaryTag(ch, mxVdxConstants.TEXT_BKGND);
    }

    /**
     * Returns the background color of text.
     *
     * @return Text background color in hexadecimal representation.
     */
    public String getTextBkgndColor() {
        String color = "";
        Element textBlock = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        if (hasSecundaryTag(textBlock, mxVdxConstants.TEXT_BKGND)) {
            color = getValueOfSecundaryTag(textBlock, mxVdxConstants.TEXT_BKGND);
            if (!color.startsWith("#")) {
                mxPropertiesManager pm = mxPropertiesManager.getInstance();
                color = String.valueOf(Integer.parseInt(color) - 1);
                color = pm.getColor(color);
            }
        }
        return color;
    }

    /**
     * Checks if the top margin of text is defined
     *
     * @return Returns <code>true</code> if the top margin of text is defined
     */
    public boolean hasTextTopMargin() {
        Element ch = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        return hasSecundaryTag(ch, mxVdxConstants.TOP_MARGIN);
    }

    /**
     * Returns the top margin of text in pixels.
     *
     * @return Numerical value of the TopMargin element
     */
    public double getTextTopMargin() {
        double margin = 0;
        Element textBlock = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        if (hasSecundaryTag(textBlock, mxVdxConstants.TOP_MARGIN)) {
            margin = getNumericalValueOfSecundaryTag(textBlock,
                    mxVdxConstants.TOP_MARGIN);
        }
        return margin;
    }

    /**
     * Checks if the bottom margin of text is defined
     *
     * @return Returns <code>true</code> if the bottom margin of text is defined.
     */
    public boolean hasTextBottomMargin() {
        Element ch = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        return hasSecundaryTag(ch, mxVdxConstants.BOTTOM_MARGIN);
    }

    /**
     * Returns the bottom margin of text in pixels.
     *
     * @return Numerical value of the BottomMargin element.
     */
    public double getTextBottomMargin() {
        double margin = 0;
        Element textBlock = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        if (hasSecundaryTag(textBlock, mxVdxConstants.BOTTOM_MARGIN)) {
            margin = getNumericalValueOfSecundaryTag(textBlock,
                    mxVdxConstants.BOTTOM_MARGIN);
        }
        return margin;
    }

    /**
     * Checks if the left margin of text is defined.
     *
     * @return Returns <code>true</code> if the left margin of text is defined.
     */
    public boolean hasTextLeftMargin() {
        Element ch = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        return hasSecundaryTag(ch, mxVdxConstants.LEFT_MARGIN);
    }

    /**
     * Returns the left margin of text in pixels.
     *
     * @return Numerical value of the LeftMargin element.
     */
    public double getTextLeftMargin() {
        double margin = 0;
        Element textBlock = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        if (hasSecundaryTag(textBlock, mxVdxConstants.LEFT_MARGIN)) {
            margin = getNumericalValueOfSecundaryTag(textBlock,
                    mxVdxConstants.LEFT_MARGIN);
        }
        return margin;
    }

    /**
     * Checks if the right margin of text is defined.
     *
     * @return Returns <code>true</code> if the right margin of text is defined.
     */
    public boolean hasTextRightMargin() {
        Element ch = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        return hasSecundaryTag(ch, mxVdxConstants.RIGHT_MARGIN);
    }

    /**
     * Returns the right margin of text in pixels.
     *
     * @return Numerical value of the RightMargin element.
     */
    public double getTextRightMargin() {
        double margin = 0;
        Element textBlock = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        if (hasSecundaryTag(textBlock, mxVdxConstants.RIGHT_MARGIN)) {
            margin = getNumericalValueOfSecundaryTag(textBlock,
                    mxVdxConstants.RIGHT_MARGIN);
        }
        return margin;
    }

    /**
     * Checks if the size of one text fragment is defined.
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if the size of one text fragment is defined.
     */
    public boolean hasTextSize(String charIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        return hasSecundaryTag(ch, mxVdxConstants.SIZE);
    }

    /**
     * Returns the size of one text fragment in pixels.
     *
     * @param charIX IX atribute of Char element
     * @return String representation of the numerical value of the Size element.
     */
    public String getTextSize(String charIX) {
        double size = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        if (hasSecundaryTag(ch, mxVdxConstants.SIZE)) {
            size = getNumericalValueOfSecundaryTag(ch, mxVdxConstants.SIZE);
        }
        return String.valueOf(size);
    }

    /**
     * Checks if the style of one text fragment is defined.
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if the style of one text fragment is defined.
     */
    public boolean hasTextStyle(String charIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        return hasSecundaryTag(ch, mxVdxConstants.STYLE);
    }

    /**
     * Returns the style of one text fragment.
     *
     * @param charIX IX atribute of Char element
     * @return String value of the Style element.
     */
    public String getTextStyle(String charIX) {
        String style = "";
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        if (hasSecundaryTag(ch, mxVdxConstants.STYLE)) {
            style = getValueOfSecundaryTag(ch, mxVdxConstants.STYLE);
        }
        return style;
    }

    /**
     * Checks if the font of one text fragment is defined
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if the font of one text fragment is defined.
     */
    public boolean hasTextFont(String charIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        return hasSecundaryTag(ch, mxVdxConstants.FONT);
    }

    /**
     * Returns the font of one text fragment
     *
     * @param charIX IX atribute of Char element
     * @return Name of the font.
     */
    public String getTextFont(String charIX) {
        String font = "";
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        if (hasSecundaryTag(ch, mxVdxConstants.FONT)) {
            font = getValueOfSecundaryTag(ch, mxVdxConstants.FONT);
        }
        mxPropertiesManager mpm = mxPropertiesManager.getInstance();
        font = mpm.getFont(font);
        return font;
    }

    /**
     * Checks if the position of one text fragment is defined
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if the position of one text fragment is defined.
     */
    public boolean hasTextPos(String charIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        return hasSecundaryTag(ch, mxVdxConstants.POS);
    }

    /**
     * Returns the position of one text fragment
     *
     * @param charIX IX atribute of Char element
     * @return Integer value of the Pos element.
     */
    public int getTextPos(String charIX) {
        int pos = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        if (hasSecundaryTag(ch, mxVdxConstants.POS)) {
            String val = getValueOfSecundaryTag(ch, mxVdxConstants.POS);
            if (!val.equals("")) {
                pos = Integer.parseInt(val);
            }
        }
        return pos;
    }

    /**
     * Checks if the strikethru of one text fragment is defined
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if the strikethru of one text fragment is defined
     */
    public boolean hasTextStrike(String charIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        return hasSecundaryTag(ch, mxVdxConstants.STRIKETHRU);
    }

    /**
     * Checks if one text fragment is Strikethru
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if one text fragment is Strikethru
     */
    public boolean getTextStrike(String charIX) {
        boolean strike = false;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        if (hasSecundaryTag(ch, mxVdxConstants.STRIKETHRU)) {
            String val = getValueOfSecundaryTag(ch, mxVdxConstants.STRIKETHRU);
            strike = val.equals("1");
        }
        return strike;
    }

    /**
     * Checks if the case of one text fragment is defined
     *
     * @param charIX IX atribute of Char element
     * @return Returns <code>true</code> if the case of one text fragment is defined.
     */
    public boolean hasTextCase(String charIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        return hasSecundaryTag(ch, mxVdxConstants.CASE);
    }

    /**
     * Returns the case property of one text fragment
     *
     * @param charIX IX atribute of Char element
     * @return Integer value of the Case element
     */
    public int getTextCase(String charIX) {
        int strike = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.CHAR, charIX);
        if (hasSecundaryTag(ch, mxVdxConstants.CASE)) {
            String val = getValueOfSecundaryTag(ch, mxVdxConstants.CASE);
            if (!val.equals("")) {
                strike = Integer.parseInt(val);
            }
        }
        return strike;
    }

    /**
     * Checks if the vertical align of text  is defined.
     *
     * @return Returns <code>true</code> if the vertical align of text  is defined.
     */
    public boolean hasVerticalAlign() {
        Element tb = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        return hasSecundaryTag(tb, mxVdxConstants.VERTICAL_ALIGN);
    }

    /**
     * Returns the vertical align property of text.
     *
     * @return Integer value of the VerticalAlign element.
     */
    public int getVerticalAlign() {
        int strike = 0;
        Element tb = getPrimaryTag(mxVdxConstants.TEXT_BLOCK);
        if (hasSecundaryTag(tb, mxVdxConstants.VERTICAL_ALIGN)) {
            String val = getValueOfSecundaryTag(tb,
                    mxVdxConstants.VERTICAL_ALIGN);
            if (!val.equals("")) {
                strike = Integer.parseInt(val);
            }
        }
        return strike;
    }

    /**
     * Checks if the angle of text is defined
     *
     * @return Returns <code>true</code> if the angle of text is defined.
     */
    public boolean hasTxtAngle() {
        Element tb = getPrimaryTag(mxVdxConstants.TEXT_X_FORM);
        return hasSecundaryTag(tb, mxVdxConstants.TXT_ANGLE);
    }

    /**
     * Returns the angle of the text.
     *
     * @return Double value of the TxtAngle element.
     */
    public double getTxtAngle() {
        double strike = 0;
        Element tb = getPrimaryTag(mxVdxConstants.TEXT_X_FORM);
        if (hasSecundaryTag(tb, mxVdxConstants.TXT_ANGLE)) {
            String val = getValueOfSecundaryTag(tb, mxVdxConstants.TXT_ANGLE);
            if (!val.equals("")) {
                strike = Double.valueOf(val);
            }
        }
        return strike;
    }

    /**
     * Checks if the horizontal align of text  is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the horizontal align of text  is defined.
     */
    public boolean hasHorizontalAlign(String paraIX) {
        Element para = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(para, mxVdxConstants.HORIZONTAL_ALIGN);
    }

    /**
     * Returns the horizontal align property of text
     *
     * @param paraIX IX atribute of Para element
     * @return Integer value of the HorizontalAlign element.
     */
    public int getHorizontalAlign(String paraIX) {
        int horizontal = 0;
        Element tb = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(tb, mxVdxConstants.HORIZONTAL_ALIGN)) {
            String val = getValueOfSecundaryTag(tb,
                    mxVdxConstants.HORIZONTAL_ALIGN);
            if (!val.equals("")) {
                horizontal = Integer.parseInt(val);
            }
        }
        return horizontal;
    }

    /**
     * Checks if the first indent of one paragraph is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the first indent of one paragraph is defined.
     */
    public boolean hasIndentFirst(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.INDENT_FIRST);
    }

    /**
     * Returns the first indent of one paragraph in pixels.
     *
     * @param paraIX IX atribute of Para element
     * @return String representation of the numerical value of the IndentFirst element.
     */
    public String getIndentFirst(String paraIX) {
        double indent = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.INDENT_FIRST)) {
            indent = getNumericalValueOfSecundaryTag(ch,
                    mxVdxConstants.INDENT_FIRST);
        }
        return String.valueOf(indent);
    }

    /**
     * Checks if the indent to left of one paragraph is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the indent to left of one paragraph is defined.
     */
    public boolean hasIndentLeft(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.INDENT_LEFT);
    }

    /**
     * Returns the indent to left of one paragraph
     *
     * @param paraIX IX atribute of Para element
     * @return String representation of the numerical value of the IndentLeft element.
     */
    public String getIndentLeft(String paraIX) {
        double indent = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.INDENT_LEFT)) {
            indent = getNumericalValueOfSecundaryTag(ch,
                    mxVdxConstants.INDENT_LEFT);
        }
        return String.valueOf(indent);
    }

    /**
     * Checks if the indent to right of one paragraph is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the indent to right of one paragraph is defined.
     */
    public boolean hasIndentRight(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.INDENT_RIGHT);
    }

    /**
     * Returns the indent to right of one paragraph
     *
     * @param paraIX IX atribute of Para element
     * @return String representation of the numerical value of the IndentRight element.
     */
    public String getIndentRight(String paraIX) {
        double indent = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.INDENT_RIGHT)) {
            indent = getNumericalValueOfSecundaryTag(ch,
                    mxVdxConstants.INDENT_RIGHT);
        }
        return String.valueOf(indent);
    }

    /**
     * Checks if the space before one paragraph is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the space before one paragraph is defined.
     */
    public boolean hasSpBefore(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.SPACE_BEFORE);
    }

    /**
     * Returns the space before one paragraph.
     *
     * @param paraIX IX atribute of Para element
     * @return String representation of the numerical value of the SpBefore element.
     */
    public String getSpBefore(String paraIX) {
        double indent = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.SPACE_BEFORE)) {
            indent = getNumericalValueOfSecundaryTag(ch,
                    mxVdxConstants.SPACE_BEFORE);
        }
        return String.valueOf(indent);
    }

    /**
     * Checks if the space after one paragraph is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the space after one paragraph is defined.
     */
    public boolean hasSpAfter(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.SPACE_AFTER);
    }

    /**
     * Returns the space after one paragraph
     *
     * @param paraIX IX atribute of Para element
     * @return String representation of the numerical value of the SpAfter element.
     */
    public String getSpAfter(String paraIX) {
        double indent = 0;
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.SPACE_AFTER)) {
            indent = getNumericalValueOfSecundaryTag(ch,
                    mxVdxConstants.SPACE_AFTER);
        }
        return String.valueOf(indent);
    }

    /**
     * Checks if the space between lines in one paragraph is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the space between lines in one paragraph is defined.
     */
    public boolean hasSpLine(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.SPACE_LINE);
    }

    /**
     * Returns the space between lines in one paragraph.
     *
     * @param paraIX IX atribute of Para element.
     * @return Double representation of the value of the SpLine element.
     */
    public double getSpLine(String paraIX) {
        double space = 0;
        String val = "";
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.SPACE_LINE)) {
            val = getValueOfSecundaryTag(ch, mxVdxConstants.SPACE_LINE);
        }
        if (!val.equals("")) {
            space = Double.parseDouble(val);
        }
        return space;
    }

    /**
     * Checks if the flags of one paragraph is defined.
     *
     * @param paraIX IX atribute of Para element.
     * @return Returns <code>true</code> if the flags of one paragraph is defined.
     */
    public boolean hasFlags(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.FLAGS);
    }

    /**
     * Returns the flags of one paragraph.
     *
     * @param paraIX IX atribute of Para element.
     * @return String value of the Flags element.
     */
    public String getFlags(String paraIX) {
        String flags = "0";
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.FLAGS)) {
            flags = getValueOfSecundaryTag(ch, mxVdxConstants.FLAGS);
        }
        return flags;
    }

    /**
     * Checks if the direction of one text fragment is defined
     *
     * @param paraIX IX atribute of Para element
     * @return Returns <code>true</code> if the direction of one text fragment is defined.
     */
    public boolean hasRTLText(String paraIX) {
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        return hasSecundaryTag(ch, mxVdxConstants.RTL_TEXT);
    }

    /**
     * Returns the direction of one text fragment.
     *
     * @param paraIX IX atribute of Para element.
     * @return String value of the RTLText.
     */
    public String getRTLText(String paraIX) {
        String flags = "ltr";
        Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
        if (hasSecundaryTag(ch, mxVdxConstants.RTL_TEXT)) {
            flags = getValueOfSecundaryTag(ch, mxVdxConstants.RTL_TEXT);
        }
        return flags;
    }

    /**
     * Checks if the space between characters in one text fragment is defined.
     *
     * @param paraIX IX atribute of Para element.
     * @return Returns <code>true</code> if the space between characters in one text fragment is defined.
     */
	public boolean hasLetterSpace(String paraIX)
	{
		Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
		return hasSecundaryTag(ch, mxVdxConstants.LETTER_SPACE);
	}

	/**
     * Returns the space between characters in one text fragment.
     *
     * @param paraIX IX atribute of Para element.
     * @return String representation of the numerical value of the Letterspace element.
     */
	public String getLetterSpace(String paraIX)
	{
		double space = 0;
		Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
		if (hasSecundaryTag(ch, mxVdxConstants.LETTER_SPACE))
		{
			space = getNumericalValueOfSecundaryTag(ch,
					mxVdxConstants.LETTER_SPACE);
		}
		return String.valueOf(space);
	}

	/**
     * Checks if the bullet element is defined.
     *
     * @param paraIX IX atribute of Para element.
     * @return Returns <code>true</code> if the bullet element is defined.
     */
	public boolean hasBullet(String paraIX)
	{
		Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
		return hasSecundaryTag(ch, mxVdxConstants.BULLET);
	}

	/**
     * Returns the bullet element value.
     *
     * @param paraIX IX atribute of Para element.
     * @return String value of the Bullet element.
     */
	public String getBullet(String paraIX)
	{
		String bullet = "0";
		Element ch = getPrimaryTagIndexed(mxVdxConstants.PARAGRAPH, paraIX);
		if (hasSecundaryTag(ch, mxVdxConstants.BULLET))
		{
			bullet = getValueOfSecundaryTag(ch, mxVdxConstants.BULLET);
		}
		return bullet;
	}
}
